#include "iic.h"

#include "device.h"

static ubyte	add8or16;
static ushort	address;
static ubyte	direction;
static ubyte	rxCount;
static ubyte	*rxData;
static ubyte	rxLen;
static ubyte	slaveAdd7;
static ubyte	txCount;
static ubyte	*txData;
static ubyte	txLen;
static ubyte	txORrx;

static void delay(void){
	for(ubyte i=40;i;i--)
		;
}
static void resetIIC(void){
	GPIO_InitTypeDef g;
	g.GPIO_Speed=GPIO_Speed_50MHz;
	g.GPIO_Pin	=PIN_I2C;
	g.GPIO_Mode	=GPIO_Mode_Out_OD;
	GPIO_SetBits(GPIOB,g.GPIO_Pin);
	GPIO_Init(GPIOB,&g);
	for(ubyte i=9;i;i--){
		GPIO_ResetBits(GPIOB,PIN_SCL);
		delay();
		GPIO_SetBits(GPIOB,PIN_SCL);
		delay();
	}
	g.GPIO_Pin	=PIN_I2C;
	g.GPIO_Mode	=GPIO_Mode_AF_OD;
	GPIO_SetBits(GPIOB,g.GPIO_Pin);
	GPIO_Init(GPIOB,&g);
	I2C_AcknowledgeConfig(I2C2,ENABLE);
}

//------------------------------------------------------------------------------

void I2C2_EV_IRQHandler(void){
	switch(I2C_GetLastEvent(I2C2)){
	case I2C_EVENT_MASTER_MODE_SELECT:					// EV5
		I2C_Send7bitAddress(I2C2,slaveAdd7,direction);
		break;
	case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
		if(add8or16==0)
			I2C_SendData(I2C2,(ubyte)(address));
		else{
			I2C_SendData(I2C2,(ubyte)((address&0xFF00)>>8));
			I2C_SendData(I2C2,(ubyte)(address&0x00FF));
		}
		if(txORrx==1)
			I2C_ITConfig(I2C2,I2C_IT_BUF,DISABLE);
		break;
	case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
		if(txCount<txLen)
			I2C_SendData(I2C2,txData[txCount++]);
		else I2C_ITConfig(I2C2,I2C_IT_BUF,DISABLE);
		break;
	case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
		if(txORrx==0){
			I2C_GenerateSTOP(I2C2,ENABLE);
			while(I2C_GetLastEvent(I2C2)==I2C_EVENT_MASTER_BYTE_TRANSMITTED)
				;
		}else{
			direction=I2C_Direction_Receiver;
			I2C_GenerateSTART(I2C2,ENABLE);
			while(I2C_GetLastEvent(I2C2)==I2C_EVENT_MASTER_BYTE_TRANSMITTED)
				;
		}
		I2C_ITConfig(I2C2,I2C_IT_BUF,ENABLE);
		break;
	case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:
		if(rxLen==1){
			I2C_AcknowledgeConfig(I2C2,DISABLE);
			I2C_GenerateSTOP(I2C2,ENABLE);
		}
		break;
	case I2C_EVENT_MASTER_BYTE_RECEIVED:
		rxData[rxCount++]=I2C_ReceiveData(I2C2);
		if(rxCount==rxLen-1){
			I2C_AcknowledgeConfig(I2C2,DISABLE);
			I2C_GenerateSTOP(I2C2,ENABLE);
		}else if(rxCount==rxLen)
			//RdTaskState = 3;
			;
	}
}

//------------------------------------------------------------------------------

void iic_init(void){
	I2C_DeInit(I2C2);
	I2C_InitTypeDef i;
	//resetIIC();
	i.I2C_Mode			=I2C_Mode_I2C;
	i.I2C_DutyCycle		=I2C_DutyCycle_2;
	i.I2C_OwnAddress1	=0x55;
	i.I2C_Ack			=I2C_Ack_Enable;
	i.I2C_AcknowledgedAddress	=I2C_AcknowledgedAddress_7bit;
	i.I2C_ClockSpeed	=500000;
	I2C_Init(I2C2,&i);
	I2C_CalculatePEC(I2C2,ENABLE);
	I2C_ITConfig(I2C2,I2C_IT_EVT|I2C_IT_BUF,ENABLE);
	I2C_Cmd(I2C2,ENABLE);
}
ubyte iic_read(ubyte device,ubyte reg,ubyte *buffer,ushort len){
	I2C_AcknowledgeConfig(I2C2,ENABLE);
	add8or16	=0;
	address		=reg;
	direction	=I2C_Direction_Transmitter;
	slaveAdd7	=device;
	rxCount		=0;
	rxData		=buffer;
	rxLen		=len;
	txCount		=0;
	txLen		=0;
	txORrx		=1;
	I2C_GenerateSTART(I2C2,ENABLE);
	return 1;
}
ubyte iic_wait(void){
	for(int i=500;i;i--){
		if(!I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY))
			return 1;
		__WFI();
	}
	resetIIC();
	return I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY)?0:1;
}
void iic_write(ubyte device,ubyte reg,ubyte *buffer,ushort len){
	I2C_AcknowledgeConfig(I2C2,ENABLE);
	add8or16	=0;
	address		=reg;
	direction	=I2C_Direction_Transmitter;
	slaveAdd7	=device;
	rxLen		=0;
	rxCount		=0;
	txLen		=len;
	txCount		=0;
	txData		=buffer;
	txORrx		=0;
	I2C_GenerateSTART(I2C2,ENABLE);
}